package com.cqq.auth.service.impl;

import java.lang.reflect.Array;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.cqq.auth.constant.AuthMessage;
import com.cqq.auth.constant.LoginStatus;
import com.cqq.auth.constant.UserStatus;
import com.cqq.auth.dao.UserDao;
import com.cqq.auth.dao.UserDataDao;
import com.cqq.auth.dao.UserGroupDao;
import com.cqq.auth.dao.UserLoginLogDao;
import com.cqq.auth.dao.domain.User;
import com.cqq.auth.dao.domain.UserData;
import com.cqq.auth.dao.domain.UserGroup;
import com.cqq.auth.dao.domain.UserLoginLog;
import com.cqq.auth.dao.query.UserQuery;
import com.cqq.auth.service.UserService;
import com.cqq.auth.service.bean.LoginInfoBean;
import com.cqq.auth.service.bean.UserBean;
import com.cqq.auth.service.bean.UserDataBean;
import com.cqq.auth.service.bean.UserQueryBean;
import com.cqq.auth.service.exception.UserLoginException;
import com.cqq.auth.service.exception.UserServiceException;
import com.cqq.common.core.base.BaseService;
import com.cqq.common.core.bean.PageInfoBean;
import com.cqq.common.core.constant.CommonMessage;
import com.cqq.common.core.util.BeanUtil;
import com.cqq.common.core.util.PasswordEncoder;
import com.cqq.common.core.util.RandomGenerator;

@Service("userService")
public class UserServiceImpl extends BaseService implements UserService {

	private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class);
	
	@Autowired
	private UserDao userDao;

	@Autowired
	private UserLoginLogDao userLoginLogDao;
	
	@Autowired
	private UserDataDao userDataDao;
	
	@Autowired
	private UserGroupDao userGroupDao;
	
//	@Value("${system.defalutPwd}")
//	private String defalutPwd;
	
	
	public UserBean addUser(UserBean user) throws UserServiceException {
		log.debug("addUser ...");
		if(user==null || StringUtils.isBlank(user.getUsername())
				|| StringUtils.isBlank(user.getPassword())
				|| user.getType()==null){
			throw super.buildException(new UserServiceException(CommonMessage.COMMON_PARAM_EMPTY));
		}
		user.setUsername(user.getUsername().toLowerCase().trim());
		User u=this.userDao.queryByUsername(user.getUsername());
		if(u!=null){
			throw super.buildException(new UserServiceException(AuthMessage.USER_EXIST));
		}
		
		user.setPassword(PasswordEncoder.encode(user.getPassword(), user.getUsername()));
		u=new User();
		BeanUtil.copy(user, u);
		u.setStatus(UserStatus.ENABLED);
		log.info("===addUser===roleids==="+u.getRoleIds()+"===");
		this.userDao.add(u);
		user.setId(u.getId());
		log.debug("addUser ok! {}",u);
		return user;
	}

	
	public void updateUser(UserBean user) throws UserServiceException {
		log.debug("updateUser ...");
		if(user==null || user.getId()==null
				|| StringUtils.isBlank(user.getUsername())
				|| user.getType()==null
				|| user.getStatus()==null){
			throw super.buildException(new UserServiceException(CommonMessage.COMMON_PARAM_EMPTY));
		}
		user.setUsername(user.getUsername().toLowerCase().trim());
		User u=this.userDao.queryByUsername(user.getUsername());
		if(u!=null && !u.getId().equals(user.getId())){
			throw super.buildException(new UserServiceException(AuthMessage.USER_EXIST));
		}
		
		if(u==null){
			u=this.userDao.queryById(user.getId());
		}
		if(u==null){
			throw super.buildException(new UserServiceException(AuthMessage.USER_NOT_EXIST));
		}
		
		BeanUtil.copy(user, u);
		log.info("===updateUser===roleids==="+u.getRoleIds()+"===");
		this.userDao.update(u);
		log.debug("updateUser ok! {}",user);
	}

	
	public UserBean findUser(Integer id) {
		if(id==null){
			return null;
		}
		User user=this.userDao.queryById(id);
		if(user==null){
			return null;
		}
		UserBean bean=new UserBean();
		BeanUtil.copy(user, bean);
		return bean;
	}

	
	public UserBean findUser(String username) {
		if(StringUtils.isBlank(username)){
			return null;
		}
		User user=userDao.queryByUsername(username.toLowerCase().trim());
		if(user==null){
			return null;
		}
		UserBean bean=new UserBean();
		BeanUtil.copy(user, bean);
		return bean;
	}

	
	public PageInfoBean<UserBean> queryUserByPage(UserQueryBean queryBean) {
		log.debug("queryUsersByPage ...");
		if(queryBean==null){
			return null;
		}
		UserQuery query=new UserQuery();
		BeanUtil.copy(queryBean, query);
		List<UserBean> beanList=null;
		Integer count=this.userDao.queryCount(query);
		if(count>0){
			List<User> users=this.userDao.queryPage(query);
			beanList=BeanUtil.copyList(users, UserBean.class);
		}
		PageInfoBean<UserBean> page=new PageInfoBean<UserBean>(beanList,count,queryBean.getPageSize(),queryBean.getPageNo());
		log.debug("queryUsersByPage ok! {}",queryBean);
		return page;		
	}

	
	public void updateUserStatus(Integer id, Integer status)
			throws UserServiceException {
		log.debug("updateUserStatus ...");
		if(id==null || status==null){
			throw super.buildException(new UserServiceException(CommonMessage.COMMON_PARAM_EMPTY));
		}
		User user=this.userDao.queryById(id);
		if(user==null){
			throw super.buildException(new UserServiceException(AuthMessage.USER_NOT_EXIST));
		}
		this.userDao.updateStatus(id, status);
		log.debug("updateUserStatus ok! id={},status={}",id,status);
	}

	
	public void updateUserPassword(Integer id, String oldPwd, String newPwd)
			throws UserServiceException {
		log.debug("updateUserPassword ...");
		if(id==null || StringUtils.isBlank(oldPwd)
				|| StringUtils.isBlank(newPwd)){
			throw super.buildException(new UserServiceException(CommonMessage.COMMON_PARAM_EMPTY));
		}
		if(oldPwd.equals(newPwd)){
			throw super.buildException(new UserServiceException(AuthMessage.USER_PASSWORD_SAME));
		}
		User user=this.userDao.queryById(id);
		if(user==null){
			throw super.buildException(new UserServiceException(AuthMessage.USER_NOT_EXIST));
		}
		
		oldPwd=PasswordEncoder.encode(oldPwd, user.getUsername());
		if(!oldPwd.equals(user.getPassword())){
			throw super.buildException(new UserServiceException(AuthMessage.USER_PASSWORD_OLD_ERROR));
		}
		
		newPwd=PasswordEncoder.encode(newPwd, user.getUsername());
		this.userDao.updatePassword(id, newPwd);
		log.debug("updateUserPassword ok! id={},oldPwd={},newPwd={}",id,oldPwd,newPwd);
	}
	
	
	public void updatePassword(Integer id,String newPwd) throws UserServiceException {
		log.debug("resetUserPassword ...");
		if(id==null){
			throw super.buildException(new UserServiceException(CommonMessage.COMMON_PARAM_EMPTY));
		}

		User user=this.userDao.queryById(id);
		if(user==null){
			throw super.buildException(new UserServiceException(AuthMessage.USER_NOT_EXIST));
		}
//		String pwd=RandomGenerator.getRandomNumberLetter(8);
		String pwd=PasswordEncoder.encode(newPwd, user.getUsername());
		this.userDao.updatePassword(id, pwd);
		log.debug("resetUserPassword ok! id={}",id);
	}
	
	
	public String resetUserPassword(Integer id) throws UserServiceException {
		log.debug("resetUserPassword ...");
		if(id==null){
			throw super.buildException(new UserServiceException(CommonMessage.COMMON_PARAM_EMPTY));
		}

		User user=this.userDao.queryById(id);
		if(user==null){
			throw super.buildException(new UserServiceException(AuthMessage.USER_NOT_EXIST));
		}
		String pwd=RandomGenerator.getRandomNumberLetter(8);
		pwd=PasswordEncoder.encode(pwd, user.getUsername());
		this.userDao.updatePassword(id, pwd);
		log.debug("resetUserPassword ok! id={}",id);
		return pwd;
	}
	
	
	public UserBean login(LoginInfoBean loginInfo) throws UserLoginException {
		if(loginInfo==null || StringUtils.isBlank(loginInfo.getUsername())
				|| StringUtils.isBlank(loginInfo.getPassword())
				|| StringUtils.isBlank(loginInfo.getSystemCode())){
			throw super.buildException(new UserLoginException(CommonMessage.COMMON_PARAM_EMPTY));
		}

		String username=loginInfo.getUsername().toLowerCase().trim();
		User user=this.userDao.queryByUsername(username);
		if(user==null){
			throw super.buildException(new UserLoginException(AuthMessage.LOGIN_USER_NOT_EXIST));
		}
		
		UserLoginLog loginLog=new UserLoginLog();
		loginLog.setUserId(user.getId());
		loginLog.setUsername(user.getUsername());
		loginLog.setRealName(user.getRealName());
		loginLog.setLoginTime(new Date());
		loginLog.setSystemCode(loginInfo.getSystemCode());
		loginLog.setLoginIp(loginInfo.getIp());
		
		try{
			if(!UserStatus.ENABLED.equals(user.getStatus())){
				throw super.buildException(new UserLoginException(AuthMessage.LOGIN_USER_STATUS_ERROR));
			}
			if(user.getEffectiveTime()!=null && user.getEffectiveTime().compareTo(new Date()) > 0){
				throw super.buildException(new UserLoginException(AuthMessage.LOGIN_EFFECTIVE_TIME_ERROR));
			}
			if(user.getExpiredTime()!=null && user.getExpiredTime().compareTo(new Date()) <= 0){
				throw super.buildException(new UserLoginException(AuthMessage.LOGIN_EXPIRED_TIME_ERROR));
			}
			String password=PasswordEncoder.encode(loginInfo.getPassword(), username);
			if(!user.getPassword().equalsIgnoreCase(password)){
				throw super.buildException(new UserLoginException(AuthMessage.LOGIN_PASSWORD_ERROR));
			}
			loginLog.setStatus(LoginStatus.SUCCESS);
		}
		catch(UserLoginException e){
			loginLog.setStatus(LoginStatus.FAILURE);
			throw e;
		}
		finally{
			this.userLoginLogDao.add(loginLog);
		}
		
		UserBean loginUser=new UserBean();
		BeanUtil.copy(user, loginUser);
		loginUser.setPassword(null);
		return loginUser;
	}

	
	public void logout() throws UserServiceException {
		/*
		Subject currentUser = SecurityUtils.getSubject();
		if(currentUser != null){
			currentUser.logout();
		}*/
	}

	
	public void updateUserRoles(Integer userId, Integer[] roleIds) throws UserServiceException {
		log.debug("updateUserRoles ...");
		if(userId==null || roleIds==null || roleIds.length==0){
			throw super.buildException(new UserServiceException(CommonMessage.COMMON_PARAM_EMPTY));
		}
		User user=this.userDao.queryById(userId);
		if(user==null){
			throw super.buildException(new UserServiceException(AuthMessage.USER_NOT_EXIST));
		}
		this.userDao.updateRoleIds(userId, roleIds);
		log.debug("updateUserRoles ok! userId={},roleIds={}", userId, roleIds);
	}

	
	public void updateUserOrganization(Integer userId, Integer[] orgIds)
			throws UserServiceException {
		log.debug("updateUserOrganization ...");
		if(userId==null){
			throw super.buildException(new UserServiceException(CommonMessage.COMMON_PARAM_EMPTY));
		}
		if(orgIds!=null && orgIds.length==0){
			orgIds=null;
		}
		User user=this.userDao.queryById(userId);
		if(user==null){
			throw super.buildException(new UserServiceException(AuthMessage.USER_NOT_EXIST));
		}
		this.userDao.updateOrgIds(userId, orgIds);
		log.debug("updateUserOrganization ok! userId={},orgIds={}", userId, orgIds);	
	}
	
	
	public List<UserBean> listUserById(List<Integer> ids) {
		if(ids==null || ids.isEmpty()){
			return null;
		}
		
		Integer[] array=(Integer[]) Array.newInstance(Integer.class, ids.size());
		List<User> users=this.userDao.queryByIds(ids.toArray(array));
		List<UserBean> beans=BeanUtil.copyList(users, UserBean.class);
		return beans;
	}

	
	public List<UserBean> listUserById(Integer[] ids) {
		if(ids==null || ids.length==0){
			return null;
		}
		List<User> users=this.userDao.queryByIds(ids);
		List<UserBean> beans=BeanUtil.copyList(users, UserBean.class);
		return beans;
	}

	
	public List<UserBean> listUserByName(String name) {
		List<User> users=this.userDao.queryByName(name);
		List<UserBean> beans=BeanUtil.copyList(users, UserBean.class);
		return beans;
	}
	
	
	public Integer[] listUserDataId(Integer userId, String dataCode) {
		UserData userData=this.userDataDao.queryByUserIdAndDataCode(userId, dataCode);
		return userData==null ? null : userData.getDataIds();
	}

	
	public List<UserBean> listUserByParentOrgId(Integer parent,String realName) {
		// TODO Auto-generated method stub
		List<User> users=userDao.queryUserByParentOrgId(parent,realName);
		List<UserBean> beans=BeanUtil.copyList(users, UserBean.class);
		return beans;
	}

	
	public List<UserBean> listUserByOrgId(Integer[] orgIds) {
		// TODO Auto-generated method stub
		if(orgIds==null || orgIds.length==0){
			return null;
		}
		List<User> users=userDao.listUserByOrgId(orgIds);
		List<UserBean> beans=BeanUtil.copyList(users, UserBean.class);
		return beans;
	}

	
	public void updateUserUserGroup(Integer userId, Integer[] userGroupIds)
			throws UserServiceException {
		// TODO Auto-generated method stub
		log.debug("updateUserRoles ...");
		if(userId==null || userGroupIds==null || userGroupIds.length==0){
			throw super.buildException(new UserServiceException(CommonMessage.COMMON_PARAM_EMPTY));
		}
		User user=this.userDao.queryById(userId);
		if(user==null){
			throw super.buildException(new UserServiceException(AuthMessage.USER_NOT_EXIST));
		}
		Integer[] roleIds=new Integer[]{};
		for (int i = 0; i < userGroupIds.length; i++) {
			UserGroup userGroup=userGroupDao.queryById(userGroupIds[i]);
			roleIds=mergeArray(roleIds,userGroup.getRoleIds());
		}
		this.userDao.updateUserUserGroup(userId, userGroupIds);
		userDao.updateRoleIds(userId, roleIds);
		log.debug("updateUserRoles ok! userId={},roleIds={}", userId, userGroupIds);
	}

	
	/**
	 * 合并两个数组并去重
	 * @param arg1
	 * @param arg2
	 * @return
	 */
	private Integer[] mergeArray(Integer[] arg1,Integer[] arg2){
		
		Set<Integer> set = new HashSet<Integer>();  
        
        for(int i = 0; i < arg1.length ; i++){  
            set.add(arg1[i]);  
        }  
        for(int i = 0; i < arg2.length ; i++){  
            set.add(arg2[i]);  
        }  
          
          
        Iterator<Integer> i = set.iterator();  
        Integer[] arrays = new Integer[set.size()];  
        int num=0;  
        while(i.hasNext()){  
            int a = (Integer)i.next();  
            arrays[num] = a;  
            num = num + 1;  
        }  
          
		return arrays;
	}

	
	public List<UserBean> queryUserByParentOrgIdandStatus(Integer parentId,
			String realName, Integer status) {
		List<User> list=userDao.queryUserByParentOrgIdandStatus(parentId, realName, status);
		List<UserBean> beans=BeanUtil.copyList(list, UserBean.class);
		return beans;
	}

	
	public List<UserBean> listUserByOrgIdAndStatus(Integer[] orgids,
			Integer status) {
		List<User> list=userDao.listUserByOrgIdAndStatus(orgids, status);
		List<UserBean> beans=BeanUtil.copyList(list, UserBean.class);
		return beans;
	}

	
	public void addUserData(UserDataBean userDataBean) {
		userDataDao.add(BeanUtil.copy(userDataBean, UserData.class));
	}

	
	public void deleteUserData(Integer userId) {
		userDataDao.deleteUserDataByUserId(userId);
	}

}
